package cn.edu.nju.ws.sview.reasoning.reasoner;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;

import cn.edu.nju.ws.sview.cache.URIIDCache;
import cn.edu.nju.ws.sview.cache.URILabelCache;
import cn.edu.nju.ws.sview.cache.URITypeCache;
import cn.edu.nju.ws.sview.crawler.Crawler;
import cn.edu.nju.ws.sview.crawler.Element;
import cn.edu.nju.ws.sview.database.DBOperations;
import cn.edu.nju.ws.sview.rdf.BlankNode;
import cn.edu.nju.ws.sview.rdf.PlainLiteral;
import cn.edu.nju.ws.sview.rdf.Resource;
import cn.edu.nju.ws.sview.rdf.ResourceFactory;
import cn.edu.nju.ws.sview.rdf.TypedLiteral;
import cn.edu.nju.ws.sview.rdf.URIResource;
import cn.edu.nju.ws.sview.reasoning.Atom;
import cn.edu.nju.ws.sview.reasoning.Constant;
import cn.edu.nju.ws.sview.reasoning.GroundAtom;
import cn.edu.nju.ws.sview.reasoning.KnowledgeBase;
import cn.edu.nju.ws.sview.reasoning.Predicate;
import cn.edu.nju.ws.sview.reasoning.Rule;
import cn.edu.nju.ws.sview.reasoning.Term;
import cn.edu.nju.ws.sview.reasoning.Variable;
import cn.edu.nju.ws.sview.reasoning.provenance.ProvenanceFactory;
import cn.edu.nju.ws.sview.servlets.ViewServlet;
import cn.edu.nju.ws.sview.util.PropertyList;
import cn.edu.nju.ws.sview.util.URIUtil;
import cn.edu.nju.ws.sview.views.CustomDataMember;
import cn.edu.nju.ws.sview.views.Entity;
import cn.edu.nju.ws.sview.views.URIDataMember;
import cn.edu.nju.ws.sview.views.data.EntityBrowsing;
import cn.edu.nju.ws.sview.wyge.relations.adataset.entities.qxliu.algorithms.ClassTree;

/**
 * 用于进行集合的过滤推理
 * @author Saisai Gong
 *
 */
public class CollectionReasoner {
	/**
	 * 启动函数，得到实体的类层次结构
	 * @param entities
	 * @param lang
	 * @return
	 */
	  public static JSONArray getClassTree(HashSet<mEntity> entities,String lang){
		  JSONArray result = null;
		  //compute classes in dereference documents
		  HashMap<Integer,String[]> map = new HashMap<Integer,String[]>();
		  for(mEntity entity:entities){
			  int etype = entity.getEtype();
			  int eid = entity.getEid();
			  if(etype!=Entity.URI_ENTITY){
				  throw new IllegalArgumentException("The entity must be uri entity");
			  }
			  try {
				HashSet<Integer> types = URITypeCache.getInstance().getTypes(eid);
				for(Integer typeID:types){
					if(!map.containsKey(typeID)){
						String uri = URIIDCache.getInstance().getURI(typeID);
						String[] array = {uri};
						map.put(typeID, array);
					}
				}
			  } catch (Throwable e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			  }
		  }
		  
		  result = getClassTree(map,lang);
		  return result;
	  }
	  
	  /**
	   * 实际计算类层次结构的构造函数
	   * @param map.包含所有类
	   * @param lang
	   * @return
	   */
	  private static JSONArray getClassTree(HashMap<Integer,String[]> map,String lang){
		  JSONArray result = null;
		try {
			result = new ClassTree(map).makeJSONForEntityClasses(lang);
		} catch (NumberFormatException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Throwable e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		  return result;
	  }
	
	  /**
	   * need to be checked when merge custom entities
	   * @return
	   */
      public static HashSet<mEntity> filterOriginMembers(int dmtype,int dmid,boolean inverse,int etype,int eid){
    	   HashSet<mEntity> result = new HashSet<mEntity>();
			/*get relevant origin uris in browsing*/
			HashSet<Integer> uris = EntityBrowsing.getEntityMembersWithoutSameas(etype, eid);
			
			HashSet<URIResource> entities = new HashSet<URIResource>();
			for(Integer id:uris){
				try {
					URIResource r = ResourceFactory.getInstance().createURIResource(URIIDCache.getInstance().getURI(id)) ;
					entities.add(r) ;
				} catch (Throwable e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			ViewReasoner viewReasoner = new ViewReasoner(entities);
			
			Predicate pred = null;
			int arity = 0;
			if(dmtype==URIDataMember.URI_DATAMEMBER){
				arity = 2;
				try {
					URIResource pred_resource = ResourceFactory.getInstance().createURIResource(
					URIIDCache.getInstance().getURI(dmid)) ;
					pred  = new Predicate(pred_resource,arity);
				} catch (Throwable e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}else if(dmtype==URIDataMember.CUSTOM_DATAMEMBER){
				/****INTERNAL_URI_PREFIX+ "dm/group/isInner/classID/isCopy/name"****/
				CustomDataMember dm = CustomDataMember.getCustomDataMemberById(dmid) ;
				arity = dm.getArity();
				String name = dm.getName();
				String group = dm.getGroup();
				boolean isInner = dm.isInner();
				boolean isCopy = dm.isCopy();
				int classID = dm.getClassID();
				URIResource pred_resource =  ResourceFactory.getInstance().createCustomDatamemberURIResource(group, name,isInner,classID,isCopy);
				pred = new Predicate(pred_resource,arity);
			}
			
			//等待取数据的元素
			HashSet<Integer> waitForData = new HashSet<Integer>();
			for(Integer uriID:uris){
				KnowledgeBase kb = new KnowledgeBase();
				kb.setViewReasoner(viewReasoner) ;
				String uri = null;
				try {
					uri = URIIDCache.getInstance().getURI(uriID);
				} catch (Throwable e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				URIResource uriResource =ResourceFactory.getInstance().createURIResource(uri);
				Constant c = new Constant(uriResource);
				
				ArrayList<Term> terms = new ArrayList<Term>();
				if(!inverse){
					terms.add(c);
					for(int i=1;i<arity;i++){
						terms.add(new Variable("x"+i));
					}
				}else if(inverse){
					/*origin uri datamember link is inverse*/
					for(int i=0;i<arity-1;i++){
						terms.add(new Variable("x"+i));
					}
					terms.add(c) ;
				}
			    
				Atom<Term> query  = new Atom<Term>(pred,terms);
				
				HashSet<GroundAtom> part = new HashSet<GroundAtom>();
				try {
					part = kb.Evaluate(query,true,true);
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			    if(part.size()>0){
			    	mEntity obj = new mEntity(Entity.URI_ENTITY,uriID);
			    	result.add(obj);
			    }else{
			    	if(!kb.isFinished())
			    		waitForData.add(uriID);
			    }
			}
			
			//对于复杂的查询，要等待获取数据的成员，我们给以6内继续执行的机会，超过6秒
			//系统认定该成员不满足filter
			long start = System.currentTimeMillis();
			while(((System.currentTimeMillis()-start)<6000)&&waitForData.size()>0){
				HashSet<Integer> removed = new HashSet<Integer>();
				for(Integer uriID:waitForData){
					KnowledgeBase kb = new KnowledgeBase();
					kb.setViewReasoner(viewReasoner) ;
					String uri = null;
					try {
						uri = URIIDCache.getInstance().getURI(uriID);
					} catch (Throwable e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					URIResource uriResource =ResourceFactory.getInstance().createURIResource(uri);
					Constant c = new Constant(uriResource);
					
					ArrayList<Term> terms = new ArrayList<Term>();
					if(!inverse){
						terms.add(c);
						for(int i=1;i<arity;i++){
							terms.add(new Variable("x"+i));
						}
					}else if(inverse){
						/*origin uri datamember link is inverse*/
						for(int i=0;i<arity-1;i++){
							terms.add(new Variable("x"+i));
						}
						terms.add(c) ;
					}
				    
					Atom<Term> query  = new Atom<Term>(pred,terms);
					
					HashSet<GroundAtom> part = new HashSet<GroundAtom>();
					try {
						part = kb.Evaluate(query,true,true);
					} catch (SQLException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				    if(part.size()>0){
				    	mEntity obj = new mEntity(Entity.URI_ENTITY,uriID);
				    	result.add(obj);
				    	removed.add(uriID);
				    }else if(kb.isFinished()){
				    	removed.add(uriID);
				    }
				}
				waitForData.removeAll(removed);
			}
			
			return result;
      }
      
      /**
	   * need to be checked when merge custom entities
	   * @return
	   */
      public static HashSet<mEntity> filterOriginMembersByMemberClass(int dmtype,int dmid,boolean inverse,int etype,int eid,HashSet<Integer> classes){
    	   HashSet<mEntity> result = new HashSet<mEntity>();
			/*get relevant origin uris in browsing*/
			HashSet<Integer> uris = EntityBrowsing.getEntityMembersWithoutSameas(etype, eid);
			
			HashSet<URIResource> entities = new HashSet<URIResource>();
			for(Integer id:uris){
				try {
					URIResource r = ResourceFactory.getInstance().createURIResource(URIIDCache.getInstance().getURI(id)) ;
					entities.add(r) ;
				} catch (Throwable e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			ViewReasoner viewReasoner = new ViewReasoner(entities);
			
			Predicate pred = null;
			int arity = 1;
			try {
				URIResource pred_resource = ResourceFactory.getInstance().createURIResource(ResourceFactory.INTERNAL_URI_PREFIX+"myq");
				pred  = new Predicate(pred_resource,arity);
			} catch (Throwable e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			ArrayList<Rule> rlist= new ArrayList<Rule>();
			for(Integer classID:classes){
				Rule r =null;
				ArrayList<Term> terms = new ArrayList<Term>();
				terms.add(new Variable("x"));
				Atom<Term> headAtom  = new Atom<Term>(pred,terms);
				ArrayList<Atom<Term>> bodyAtoms = new ArrayList<Atom<Term>>();
				try {
					URIResource class_pred_resource = ResourceFactory.getInstance().createURIResource(URIIDCache.getInstance().getURI(classID));
					Predicate class_pred  = new Predicate(class_pred_resource,arity);
					Atom<Term> bodyAtom =  new Atom<Term>(class_pred,terms);
					bodyAtoms.add(bodyAtom);
				} catch (Throwable e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				r = new Rule(headAtom,bodyAtoms,ProvenanceFactory.getInstance().createProvFromTemporary());
				rlist.add(r);
			}
			
			//等待取数据的元素
			HashSet<Integer> waitForData = new HashSet<Integer>();
			for(Integer uriID:uris){
				KnowledgeBase kb = new KnowledgeBase();
				kb.setViewReasoner(viewReasoner);
				for(Rule r:rlist){
					kb.addRule(r);
				}
				String uri = null;
				try {
					uri = URIIDCache.getInstance().getURI(uriID);
				} catch (Throwable e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				URIResource uriResource = ResourceFactory.getInstance()
						.createURIResource(uri);
				Constant c = new Constant(uriResource);

				ArrayList<Term> terms = new ArrayList<Term>();
				terms.add(c);

				Atom<Term> query = new Atom<Term>(pred, terms);

				HashSet<GroundAtom> part = new HashSet<GroundAtom>();
				try {
					part = kb.Evaluate(query, true, true);
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				if (part.size() > 0) {
					mEntity obj = new mEntity(Entity.URI_ENTITY, uriID);
					result.add(obj);
				} else {
					if (!kb.isFinished())
						waitForData.add(uriID);
				}
			}
			
			//对于复杂的查询，要等待获取数据的成员，我们给以6内继续执行的机会，超过6秒
			//系统认定该成员不满足filter
			long start = System.currentTimeMillis();
			while(((System.currentTimeMillis()-start)<6000)&&waitForData.size()>0){
				HashSet<Integer> removed = new HashSet<Integer>();
				for(Integer uriID:waitForData){
					KnowledgeBase kb = new KnowledgeBase();
					kb.setViewReasoner(viewReasoner) ;
					String uri = null;
					try {
						uri = URIIDCache.getInstance().getURI(uriID);
					} catch (Throwable e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					URIResource uriResource =ResourceFactory.getInstance().createURIResource(uri);
					Constant c = new Constant(uriResource);
					
					ArrayList<Term> terms = new ArrayList<Term>();
					terms.add(c) ;
				    
					Atom<Term> query  = new Atom<Term>(pred,terms);
					
					HashSet<GroundAtom> part = new HashSet<GroundAtom>();
					try {
						part = kb.Evaluate(query,true,true);
					} catch (SQLException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				    if(part.size()>0){
				    	mEntity obj = new mEntity(Entity.URI_ENTITY,uriID);
				    	result.add(obj);
				    	removed.add(uriID);
				    }else if(kb.isFinished()){
				    	removed.add(uriID);
				    }
				}
				waitForData.removeAll(removed);
			}
			
			return result;
      }
      
      /**
	   * need to be checked when merge custom entities
	   * @return
	   */
      public static HashSet<mEntity> filterOriginMembersByValueClass(int dmtype,int dmid,boolean inverse,int etype,int eid,HashSet<Integer> classes){
    	   HashSet<mEntity> result = new HashSet<mEntity>();
			/*get relevant origin uris in browsing*/
			HashSet<Integer> uris = EntityBrowsing.getEntityMembersWithoutSameas(etype, eid);
			
			HashSet<URIResource> entities = new HashSet<URIResource>();
			for(Integer id:uris){
				try {
					URIResource r = ResourceFactory.getInstance().createURIResource(URIIDCache.getInstance().getURI(id)) ;
					entities.add(r) ;
				} catch (Throwable e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			ViewReasoner viewReasoner = new ViewReasoner(entities);
            
			Predicate qpred = null;
			int qarity = 1;
			try {
				URIResource qpred_resource = ResourceFactory.getInstance().createURIResource(ResourceFactory.INTERNAL_URI_PREFIX+"myq");
				qpred  = new Predicate(qpred_resource,qarity);
			} catch (Throwable e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			
			Predicate dmpred = null;
			int arity = 0;
			if(dmtype==URIDataMember.URI_DATAMEMBER){
				arity = 2;
				try {
					URIResource pred_resource = ResourceFactory.getInstance().createURIResource(
					URIIDCache.getInstance().getURI(dmid)) ;
					dmpred  = new Predicate(pred_resource,arity);
				} catch (Throwable e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}else if(dmtype==URIDataMember.CUSTOM_DATAMEMBER){
				/****INTERNAL_URI_PREFIX+ "dm/group/isInner/classID/isCopy/name"****/
				CustomDataMember dm = CustomDataMember.getCustomDataMemberById(dmid) ;
				arity = dm.getArity();
				String name = dm.getName();
				String group = dm.getGroup();
				boolean isInner = dm.isInner();
				boolean isCopy = dm.isCopy();
				int classID = dm.getClassID();
				URIResource pred_resource =  ResourceFactory.getInstance().createCustomDatamemberURIResource(group, name,isInner,classID,isCopy);
				dmpred = new Predicate(pred_resource,arity);
			}
			
			ArrayList<Term> headterms = new ArrayList<Term>();
			headterms.add(new Variable("x"));
			ArrayList<Term> bodyterms = new ArrayList<Term>();
			if(inverse){
				bodyterms.add(new Variable("y"));
				bodyterms.add(new Variable("x"));
			}else{
				bodyterms.add(new Variable("x"));
				bodyterms.add(new Variable("y"));
			}
			Atom<Term> batom =  new Atom<Term>(dmpred,bodyterms);
			ArrayList<Term> classterms = new ArrayList<Term>();
			classterms.add(new Variable("y"));
			ArrayList<Rule> rlist= new ArrayList<Rule>();
			for(Integer classID:classes){
				Rule r =null;
				Atom<Term> headAtom  = new Atom<Term>(qpred,headterms);
				ArrayList<Atom<Term>> bodyAtoms = new ArrayList<Atom<Term>>();
				bodyAtoms.add(batom);
				try {
					URIResource class_pred_resource = ResourceFactory.getInstance().createURIResource(URIIDCache.getInstance().getURI(classID));
					Predicate class_pred  = new Predicate(class_pred_resource,1);
					Atom<Term> classAtom =  new Atom<Term>(class_pred,classterms);
					bodyAtoms.add(classAtom);
				} catch (Throwable e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				r = new Rule(headAtom,bodyAtoms,ProvenanceFactory.getInstance().createProvFromTemporary());
				rlist.add(r);
			}
			
			//等待取数据的元素
			HashSet<Integer> waitForData = new HashSet<Integer>();
			for(Integer uriID:uris){
				KnowledgeBase kb = new KnowledgeBase();
				kb.setViewReasoner(viewReasoner);
				for(Rule r:rlist){
					kb.addRule(r);
				}
				String uri = null;
				try {
					uri = URIIDCache.getInstance().getURI(uriID);
				} catch (Throwable e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				URIResource uriResource = ResourceFactory.getInstance()
						.createURIResource(uri);
				Constant c = new Constant(uriResource);

				ArrayList<Term> terms = new ArrayList<Term>();
				terms.add(c);

				Atom<Term> query = new Atom<Term>(qpred, terms);

				HashSet<GroundAtom> part = new HashSet<GroundAtom>();
				try {
					part = kb.Evaluate(query, true, true);
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				if (part.size() > 0) {
					mEntity obj = new mEntity(Entity.URI_ENTITY, uriID);
					result.add(obj);
				} else {
					if (!kb.isFinished())
						waitForData.add(uriID);
				}
			}
			
			//对于复杂的查询，要等待获取数据的成员，我们给以6内继续执行的机会，超过6秒
			//系统认定该成员不满足filter
			long start = System.currentTimeMillis();
			while(((System.currentTimeMillis()-start)<6000)&&waitForData.size()>0){
				HashSet<Integer> removed = new HashSet<Integer>();
				for(Integer uriID:waitForData){
					KnowledgeBase kb = new KnowledgeBase();
					kb.setViewReasoner(viewReasoner) ;
					String uri = null;
					try {
						uri = URIIDCache.getInstance().getURI(uriID);
					} catch (Throwable e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					URIResource uriResource =ResourceFactory.getInstance().createURIResource(uri);
					Constant c = new Constant(uriResource);
					
					ArrayList<Term> terms = new ArrayList<Term>();
					terms.add(c) ;
				    
					Atom<Term> query  = new Atom<Term>(qpred,terms);
					
					HashSet<GroundAtom> part = new HashSet<GroundAtom>();
					try {
						part = kb.Evaluate(query,true,true);
					} catch (SQLException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				    if(part.size()>0){
				    	mEntity obj = new mEntity(Entity.URI_ENTITY,uriID);
				    	result.add(obj);
				    	removed.add(uriID);
				    }else if(kb.isFinished()){
				    	removed.add(uriID);
				    }
				}
				waitForData.removeAll(removed);
			}
			
			return result;
      }      
      
      /**
	   * need to be checked when merge custom entities
	   * @return
	   */
      public static HashSet<mEntity> filterOriginMembersByEqual(int dmtype,int dmid,boolean inverse,int etype,int eid,HashSet<Resource> resources){
    	   HashSet<mEntity> result = new HashSet<mEntity>();
			/*get relevant origin uris in browsing*/
			HashSet<Integer> uris = EntityBrowsing.getEntityMembersWithoutSameas(etype, eid);
			
			HashSet<URIResource> entities = new HashSet<URIResource>();
			for(Integer id:uris){
				try {
					URIResource r = ResourceFactory.getInstance().createURIResource(URIIDCache.getInstance().getURI(id)) ;
					entities.add(r) ;
				} catch (Throwable e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			ViewReasoner viewReasoner = new ViewReasoner(entities);
			
			Predicate pred = null;
			int arity = 0;
			if(dmtype==URIDataMember.URI_DATAMEMBER){
				arity = 2;
				try {
					URIResource pred_resource = ResourceFactory.getInstance().createURIResource(
					URIIDCache.getInstance().getURI(dmid)) ;
					pred  = new Predicate(pred_resource,arity);
				} catch (Throwable e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}else if(dmtype==URIDataMember.CUSTOM_DATAMEMBER){
				/****INTERNAL_URI_PREFIX+ "dm/group/isInner/classID/isCopy/name"****/
				CustomDataMember dm = CustomDataMember.getCustomDataMemberById(dmid) ;
				arity = dm.getArity();
				String name = dm.getName();
				String group = dm.getGroup();
				boolean isInner = dm.isInner();
				boolean isCopy = dm.isCopy();
				int classID = dm.getClassID();
				URIResource pred_resource =  ResourceFactory.getInstance().createCustomDatamemberURIResource(group, name,isInner,classID,isCopy);
				pred = new Predicate(pred_resource,arity);
			}
			
			//等待取数据的元素
			HashSet<Integer> waitForData = new HashSet<Integer>();
			for(Integer uriID:uris){
			for (Resource r : resources) {
				Constant mconst = new Constant(r);
				KnowledgeBase kb = new KnowledgeBase();
				kb.setViewReasoner(viewReasoner);
				String uri = null;
				try {
					uri = URIIDCache.getInstance().getURI(uriID);
				} catch (Throwable e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				URIResource uriResource = ResourceFactory.getInstance()
						.createURIResource(uri);
				Constant c = new Constant(uriResource);

				ArrayList<Term> terms = new ArrayList<Term>();
				if(arity!=2){
					throw new IllegalArgumentException("The num of arguments must be two");
				}
				if (!inverse) {
					terms.add(c);
					terms.add(mconst);
				} else if (inverse) {
					/* origin uri datamember link is inverse */
					terms.add(mconst);
					terms.add(c);
				}

				Atom<Term> query = new Atom<Term>(pred, terms);

				HashSet<GroundAtom> part = new HashSet<GroundAtom>();
				try {
					part = kb.Evaluate(query, true, true);
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				if (part.size() > 0) {
					mEntity obj = new mEntity(Entity.URI_ENTITY, uriID);
					result.add(obj);
				} else {
					if (!kb.isFinished())
						waitForData.add(uriID);
				}
			}
			}
			
			//对于复杂的查询，要等待获取数据的成员，我们给以6内继续执行的机会，超过6秒
			//系统认定该成员不满足filter
			long start = System.currentTimeMillis();
			while(((System.currentTimeMillis()-start)<6000)&&waitForData.size()>0){
				HashSet<Integer> removed = new HashSet<Integer>();
				for(Integer uriID:waitForData){
					KnowledgeBase kb = new KnowledgeBase();
					kb.setViewReasoner(viewReasoner) ;
					String uri = null;
					try {
						uri = URIIDCache.getInstance().getURI(uriID);
					} catch (Throwable e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					URIResource uriResource =ResourceFactory.getInstance().createURIResource(uri);
					Constant c = new Constant(uriResource);
					
					ArrayList<Term> terms = new ArrayList<Term>();
					if(!inverse){
						terms.add(c);
						for(int i=1;i<arity;i++){
							terms.add(new Variable("x"+i));
						}
					}else if(inverse){
						/*origin uri datamember link is inverse*/
						for(int i=0;i<arity-1;i++){
							terms.add(new Variable("x"+i));
						}
						terms.add(c) ;
					}
				    
					Atom<Term> query  = new Atom<Term>(pred,terms);
					
					HashSet<GroundAtom> part = new HashSet<GroundAtom>();
					try {
						part = kb.Evaluate(query,true,true);
					} catch (SQLException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				    if(part.size()>0){
				    	mEntity obj = new mEntity(Entity.URI_ENTITY,uriID);
				    	result.add(obj);
				    	removed.add(uriID);
				    }else if(kb.isFinished()){
				    	removed.add(uriID);
				    }
				}
				waitForData.removeAll(removed);
			}
			
			return result;
      }
      
      /**
  	 * 计算集合取值对应的类层次结构
  	 * need to be checke: 只是考虑了类型为uri的取值具有的类层次结构
  	 * @param dmtype
  	 * @param dmid
  	 * @param inverse
  	 * @param lang
  	 * @param memberjson
  	 * @return
  	 */
  	public static HashSet<Integer> computeCollectionDMValueClass(int dmtype, int dmid,
  			int inverse, String lang, JSONArray memberjson) {
  		HashSet<Integer> classes = new HashSet<Integer>();
		HashSet<Integer> uris = new HashSet<Integer>();
		for (int i = 0; i < memberjson.size(); i++) {
			JSONObject memob = (JSONObject) memberjson.get(i);
			int etype = Entity.transTypeStr2ID((String) memob.get("etype"));
			int eid = Integer.valueOf((String) memob.get("eid"));
			if (etype != Entity.URI_ENTITY) {
				throw new IllegalArgumentException("Member must be uri entity");
			}
			uris.add(eid);
		}

		HashSet<URIResource> entities = new HashSet<URIResource>();
		for (Integer id : uris) {
			try {
				URIResource r = ResourceFactory.getInstance()
						.createURIResource(URIIDCache.getInstance().getURI(id));
				entities.add(r);
			} catch (Throwable e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		ViewReasoner viewReasoner = new ViewReasoner(entities);

		HashSet<GroundAtom> reasoningRes = new HashSet<GroundAtom>();
		// 等待取数据的元素
		HashSet<Integer> waitForData = new HashSet<Integer>();

		Predicate pred = null;
		int arity = 0;
		if (dmtype == URIDataMember.URI_DATAMEMBER) {
			arity = 2;
			try {
				URIResource pred_resource = ResourceFactory.getInstance()
						.createURIResource(
								URIIDCache.getInstance().getURI(dmid));
				pred = new Predicate(pred_resource, arity);
			} catch (Throwable e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} else if (dmtype == URIDataMember.CUSTOM_DATAMEMBER) {
			/**** INTERNAL_URI_PREFIX+ "dm/group/isInner/classID/isCopy/name" ****/
			CustomDataMember dm = CustomDataMember
					.getCustomDataMemberById(dmid);
			arity = dm.getArity();
			String name = dm.getName();
			String group = dm.getGroup();
			boolean isInner = dm.isInner();
			boolean isCopy = dm.isCopy();
			int classID = dm.getClassID();
			URIResource pred_resource = ResourceFactory.getInstance()
					.createCustomDatamemberURIResource(group, name, isInner,
							classID, isCopy);
			pred = new Predicate(pred_resource, arity);
		}
		for (Integer uriID : uris) {
			KnowledgeBase kb = new KnowledgeBase();
			kb.setViewReasoner(viewReasoner);
			String uri = null;
			try {
				uri = URIIDCache.getInstance().getURI(uriID);
			} catch (Throwable e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			URIResource uriResource = ResourceFactory.getInstance()
					.createURIResource(uri);
			Constant c = new Constant(uriResource);

			ArrayList<Term> terms = new ArrayList<Term>();
			if (inverse == 0) {
				terms.add(c);
				for (int i = 1; i < arity; i++) {
					terms.add(new Variable("x" + i));
				}
			} else if (inverse == 1) {
				/* origin uri datamember link is inverse */
				for (int i = 0; i < arity - 1; i++) {
					terms.add(new Variable("x" + i));
				}
				terms.add(c);
			}

			Atom<Term> query = new Atom<Term>(pred, terms);

			HashSet<GroundAtom> part = new HashSet<GroundAtom>();
			try {
				part = kb.Evaluate(query, true);
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			reasoningRes.addAll(part);
			if (!kb.isFinished()) {
				waitForData.add(uriID);
			}
		}

		// 对于复杂的查询，要等待获取数据的成员，我们给以6内继续执行的机会，超过6秒
		// 系统认定该成员不再具有额外的取值
		long start = System.currentTimeMillis();
		while (((System.currentTimeMillis() - start) < 6000)
				&& waitForData.size() > 0) {
			HashSet<Integer> removed = new HashSet<Integer>();
			for (Integer uriID : waitForData) {
				KnowledgeBase kb = new KnowledgeBase();
				kb.setViewReasoner(viewReasoner);
				String uri = null;
				try {
					uri = URIIDCache.getInstance().getURI(uriID);
				} catch (Throwable e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				URIResource uriResource = ResourceFactory.getInstance()
						.createURIResource(uri);
				Constant c = new Constant(uriResource);

				ArrayList<Term> terms = new ArrayList<Term>();
				if (inverse == 0) {
					terms.add(c);
					for (int i = 1; i < arity; i++) {
						terms.add(new Variable("x" + i));
					}
				} else if (inverse == 1) {
					/* origin uri datamember link is inverse */
					for (int i = 0; i < arity - 1; i++) {
						terms.add(new Variable("x" + i));
					}
					terms.add(c);
				}

				Atom<Term> query = new Atom<Term>(pred, terms);

				HashSet<GroundAtom> part = new HashSet<GroundAtom>();
				try {
					part = kb.Evaluate(query, true);
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				reasoningRes.addAll(part);
				if (kb.isFinished()) {
					removed.add(uriID);
				}
			}
			waitForData.removeAll(removed);
		}
		/*开始计算取值具有的类层次结构*/
		for (GroundAtom groudAtom : reasoningRes) {
  			ArrayList<Constant> array = groudAtom.getTerms();
  			if (arity == 2) {
  				Resource resource = null;
  				if (inverse == 0) {
  					Constant constant = array.get(1);
  					resource = constant.getResource();
  				} else if (inverse == 1) {
  					Constant constant = array.get(0);
  					resource = constant.getResource();
  				}
  				//只考虑类型为uri的取值
  				if(resource instanceof URIResource){
  					URIResource uriRes = (URIResource)resource;
  					int id = uriRes.getID();
  					try {
						classes.addAll(URITypeCache.getInstance().getTypes(id));
					} catch (Throwable e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
  				}
               
  			} else {
  				throw new IllegalArgumentException(
  						"The arity of predicate must be 2");
  			}
  		}
		return classes;
  	}
      
      
      /**
       * For CollectionServlet.java 计算集合取值
       * @param dmtype
       * @param dmid
       * @param inverse
       * @param lang
       * @param memberjson
       * @param valueArray 取值json数组
       * @param docArray 推理设计数据源json数组
       * @return.first:waitfordata second waitforlabel
       */
  	public static ArrayList<Boolean> computeCollectionDMValue(int dmtype, int dmid,
  			int inverse, String lang, JSONArray memberjson,JSONArray valueArray,JSONArray  docArray ) {
  		HashSet<Integer> uris = new HashSet<Integer>();
  		for (int i = 0; i < memberjson.size(); i++) {
  			JSONObject memob = (JSONObject) memberjson.get(i);
  			int etype = Entity.transTypeStr2ID((String) memob.get("etype"));
  			int eid = Integer.valueOf((String) memob.get("eid"));
  			if (etype != Entity.URI_ENTITY) {
  				throw new IllegalArgumentException("Member must be uri entity");
  			}
  			uris.add(eid);
  		}

  		HashSet<URIResource> entities = new HashSet<URIResource>();
  		for (Integer id : uris) {
  			try {
  				URIResource r = ResourceFactory.getInstance()
  						.createURIResource(URIIDCache.getInstance().getURI(id));
  				entities.add(r);
  			} catch (Throwable e) {
  				// TODO Auto-generated catch block
  				e.printStackTrace();
  			}
  		}
  		ViewReasoner viewReasoner = new ViewReasoner(entities);

  		boolean waitData = false;

  		HashSet<GroundAtom> reasoningRes = new HashSet<GroundAtom>();

  		Predicate pred = null;
  		int arity = 0;
  		if (dmtype == URIDataMember.URI_DATAMEMBER) {
  			arity = 2;
  			try {
  				URIResource pred_resource = ResourceFactory.getInstance()
  						.createURIResource(
  								URIIDCache.getInstance().getURI(dmid));
  				pred = new Predicate(pred_resource, arity);
  			} catch (Throwable e) {
  				// TODO Auto-generated catch block
  				e.printStackTrace();
  			}
  		} else if (dmtype == URIDataMember.CUSTOM_DATAMEMBER) {
  			/**** INTERNAL_URI_PREFIX+ "dm/group/isInner/classID/isCopy/name" ****/
  			CustomDataMember dm = CustomDataMember
  					.getCustomDataMemberById(dmid);
  			arity = dm.getArity();
  			String name = dm.getName();
  			String group = dm.getGroup();
  			boolean isInner = dm.isInner();
  			boolean isCopy = dm.isCopy();
  			int classID = dm.getClassID();
  			URIResource pred_resource = ResourceFactory.getInstance()
  					.createCustomDatamemberURIResource(group, name, isInner,
  							classID, isCopy);
  			pred = new Predicate(pred_resource, arity);
  		}
  	   //推理用到的相关数据源
		HashSet<String> srcDocs = new HashSet<String>();
  		for (Integer uriID : uris) {
  			KnowledgeBase kb = new KnowledgeBase();
  			kb.setViewReasoner(viewReasoner);
  			String uri = null;
  			try {
  				uri = URIIDCache.getInstance().getURI(uriID);
  			} catch (Throwable e) {
  				// TODO Auto-generated catch block
  				e.printStackTrace();
  			}
  			URIResource uriResource = ResourceFactory.getInstance()
  					.createURIResource(uri);
  			Constant c = new Constant(uriResource);

  			ArrayList<Term> terms = new ArrayList<Term>();
  			if (inverse == 0) {
  				terms.add(c);
  				for (int i = 1; i < arity; i++) {
  					terms.add(new Variable("x" + i));
  				}
  			} else if (inverse == 1) {
  				/* origin uri datamember link is inverse */
  				for (int i = 0; i < arity - 1; i++) {
  					terms.add(new Variable("x" + i));
  				}
  				terms.add(c);
  			}

  			Atom<Term> query = new Atom<Term>(pred, terms);

  			HashSet<GroundAtom> part = new HashSet<GroundAtom>();
  			try {
  				part = kb.Evaluate(query, true,srcDocs);
  			} catch (SQLException e) {
  				// TODO Auto-generated catch block
  				e.printStackTrace();
  			}
  			reasoningRes.addAll(part);
  			if (!kb.isFinished()) {
  				waitData = true;
  			}
  		}

		for(String doc:srcDocs){
			int docID = 0;
			try {
				docID = URIIDCache.getInstance().getURIID(doc, true);
			} catch (Throwable e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			JSONObject docObj = new JSONObject();
			docObj.put("id",docID);
			docObj.put("uri", doc);
			docArray.add(docObj);
		}
  		
  		/* If the uri's label of lang is unknown, dereference the uri */
  		boolean waitForLabelExtract = false;

  		int fetchLabelNum = 0;
  		// 由于前台需要显示拥有每个取值的成员情况，而在客户端做效率太低，大数据量集合浏览容易引起浏览器死机，所以放在服务器端做
  		HashMap<Resource, HashSet<URIResource>> map = new HashMap<Resource, HashSet<URIResource>>();
  		for (GroundAtom groudAtom : reasoningRes) {
  			ArrayList<Constant> array = groudAtom.getTerms();
  			if (arity == 2) {
  				Resource resource = null;
  				URIResource memberResource = null;
  				if (inverse == 0) {
  					Constant constant = array.get(1);
  					resource = constant.getResource();
  					memberResource = (URIResource) array.get(0).getResource();
  				} else if (inverse == 1) {
  					Constant constant = array.get(0);
  					resource = constant.getResource();
  					memberResource = (URIResource) array.get(1).getResource();
  				}

  				HashSet<URIResource> memberSet = map.get(resource);
  				if (memberSet == null) {
  					memberSet = new HashSet<URIResource>();
  					map.put(resource, memberSet);
  				}
  				memberSet.add(memberResource);
  			} else {
  				throw new IllegalArgumentException(
  						"The arity of predicate must be 2");
  			}
  		}
  		for (Resource resource : map.keySet()) {
  			JSONObject jsob = new JSONObject();

  			String valueLabel = null;
  			int entityID = 0;
  			String etype = null;
  			String literalLang = null;
  			int literalDatatypeID = -1;
  			String euri = null;
  			boolean needLabel = false;

  			if (resource instanceof PlainLiteral) {
  				PlainLiteral literal = (PlainLiteral) resource;
  				if (literal.getLanguageTag().startsWith(lang)) {
  					valueLabel = literal.getLexicalForm();
  					etype = "l";
  					entityID = valueLabel.hashCode();
  					literalLang = literal.getLanguageTag();
  				} else if (lang.equals("en")
  						&& literal.getLanguageTag().equals("")) {
  					valueLabel = literal.getLexicalForm();
  					etype = "l";
  					entityID = valueLabel.hashCode();
  					literalLang = literal.getLanguageTag();
  				} else
  					continue;

  			} else if (resource instanceof TypedLiteral) {
  				TypedLiteral literal = (TypedLiteral) resource;
  				valueLabel = literal.getLexicalForm();
  				etype = "l";
  				entityID = valueLabel.hashCode();
  				literalDatatypeID = literal.getDatatypeURI().getID();
  			} else if (resource instanceof BlankNode) {
  				/* remove blank nodes */
  				continue;
  			} else {
  				URIResource uri_resource = (URIResource) resource;
  				euri = uri_resource.getURI();
  				etype = Entity.URI_ENTITY_Str;
  				try {
  					entityID = URIIDCache.getInstance().getURIID(
  							uri_resource.getURI(), false);
  				} catch (Throwable e) {
  					// TODO Auto-generated catch block
  					e.printStackTrace();
  				}
				try {
					valueLabel = URILabelCache.getInstance().getLabel(entityID, lang) ;
					if(valueLabel.equals("")){
						valueLabel = URIUtil.getLocalname(uri_resource.getURI()) ;
						/*not get the label of the lang ,need to dereference the doc
						 * and discard this result
						 * */
						String status = DBOperations.getValidStatus(entityID);
						if(!status.equals(URIResource.VALID)&&
								Crawler.getInstance().checkStatus(uri_resource)==Crawler.STATUS_UNSUBMITTED){
						      needLabel  =true;
						}
					}
				} catch (Throwable e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
  			}

  			/* 对于homepage等属性做特殊处理 */
  			if (dmtype == URIDataMember.URI_DATAMEMBER) {
  				HashSet<Integer> directuriset = PropertyList
  						.getDirectURIProperties();
  				HashSet<Integer> directlabelset = PropertyList
  						.getDirectLabelProperties();
  				if (directuriset.contains(dmid)) {
  					jsob.put("directuri", 1);
  					needLabel = false;
  				} else if (directlabelset.contains(dmid)) {
  					jsob.put("directlabel", 1);
  					needLabel = false;
  				}
  			}

  			if (etype.equals(Entity.URI_ENTITY_Str)) {
  				if (euri.startsWith("http://") || euri.startsWith("https://")) {
  					if (euri.endsWith(".jpg") || euri.endsWith(".png")
  							|| euri.endsWith(".bmp") || euri.endsWith(".jpeg")
  							|| euri.endsWith(".gif") || euri.endsWith(".ico")) {
  						jsob.put("isimage", 1);
  						needLabel = false;
  					}
  				}
  			}

  			jsob.put("valueLabel", valueLabel);
  			jsob.put("etype", etype);
  			jsob.put("eid", entityID);
  			jsob.put("euri", euri);
  			jsob.put("needLabel", needLabel);
  			jsob.put("literalLang", literalLang);
  			jsob.put("literalType", literalDatatypeID);

  			JSONArray memberArray = new JSONArray();
  			for (URIResource memberResource : map.get(resource)) {
  				int memberType = -1;
  				int memberID = -1;
  				String memberLabel = null;
  				JSONObject membObj = new JSONObject();
  				memberType = Entity.URI_ENTITY;
  				memberID = memberResource.getID();
  				memberLabel = memberResource.getLabel(memberID, lang);
  				membObj.put("memberType", Entity.transTypeID2Str(memberType));
  				membObj.put("memberID", memberID);
  				membObj.put("memberLabel", memberLabel);
  				memberArray.add(membObj);
  			}
  			jsob.put("memberArray", memberArray);
  			valueArray.add(jsob);
  		}
  		
  		ArrayList<Boolean> flags = new ArrayList<Boolean>();
  		flags.add(waitData);
  		flags.add(waitForLabelExtract);
  		return flags;
  	}      
      
      public static class mEntity{
    	  int etype;
    	  int eid;
    	  public mEntity(int etype,int eid){
    		  this.etype = etype;
    		  this.eid = eid;
    	  }
    	  
    	  public int getEtype(){
    		  return this.etype;
    	  }
    	  public int getEid(){
    		  return this.eid;
    	  }

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + eid;
			result = prime * result + etype;
			return result;
		}

		@Override
		public boolean equals(java.lang.Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			mEntity other = (mEntity) obj;
			if (eid != other.eid)
				return false;
			if (etype != other.etype)
				return false;
			return true;
		}
    	  
      }
}
